﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using DataModels.Common;
using DataModels.Models;
using GenericTools;
using GenericTools.Models;
using GenericTools.OptionBPlus;
using ReportingManagement.Components.DHIS;
using System.Windows.Interop;

namespace ReportingManagement.Components
{

    /// <summary>
    /// Interaction logic for MTUHAReport.xaml
    /// </summary>
    public partial class ANCMTUHAReport : UserControl
    {
        public event EventHandler<InteroperableUserControlEventArgs> StatusChanged;

        private enum Direction
        {
            UP, DOWN, LEFT, RIGHT
        }

        /// <summary>
        /// View mode
        /// </summary>
        public enum ViewMode
        {
            /// <summary>
            /// Editing
            /// </summary>
            EDITING = 1,

            /// <summary>
            /// Read-only
            /// </summary>
            READ_ONLY = 2
        }

        private FullMTUHAReport mtuhaReport;
        private UserInformation user; 
        private BackgroundWorker backgroundWorker;

        private ViewMode _mode;
        public ViewMode Mode
        {
            get { return _mode; }
            set
            {
                _mode = value;
                UpdateViewMode();
            }
        }

        private void UpdateViewMode()
        {
            switch (_mode)
            {
                case ANCMTUHAReport.ViewMode.EDITING:
                    btnGetReport.Visibility = System.Windows.Visibility.Collapsed;
                    gridActionPanel.Visibility = System.Windows.Visibility.Visible;
                    foreach (UIElement element in grid.Children)
                    {
                        var textBox = element as TextBox;
                        if (textBox != null) if (textBox.Focusable) textBox.IsReadOnly = false;
                    }
                    break;

                case ANCMTUHAReport.ViewMode.READ_ONLY:                    
                    btnGetReport.Visibility = System.Windows.Visibility.Visible;
                    gridActionPanel.Visibility = System.Windows.Visibility.Collapsed;
                    foreach (UIElement element in grid.Children)
                    {
                        var textBox = element as TextBox;
                        if (textBox != null) if (textBox.Focusable) textBox.IsReadOnly = true;
                    }
                    break;
            }
        }

        // Making sure this is set up in the codes
        [Browsable(false)]
        public UserInformation User
        {
            get { return this.user; }
            set
            {
                this.user = value;
                if (regions == null)
                {
                    progressBar.Visibility = Visibility.Visible;
                    lblProgress.Visibility = Visibility.Visible;
                    cboRegion.IsEnabled = false;
                    cboDistrict.IsEnabled = false;
                    cboFacility.IsEnabled = false;
                    cboReportYear.IsEnabled = false;
                    cboReportMonth.IsEnabled = false;
                    btnGetReport.IsEnabled = false;
                    btnSave.IsEnabled = false;
                    btnReset.IsEnabled = false;
                    loadingRegions = true;
                    backgroundWorker.RunWorkerAsync();
                    var args = new InteroperableUserControlEventArgs
                    {
                        StatusText = "Loading regions, districts and facilities. Please wait...",
                        Type = InteroperableUserControlEventArgs.StatusType.Text
                    };
                    if (StatusChanged != null) StatusChanged(this, args);
                }
                else
                {
                    cboRegion.ItemsSource = regions;
                    PopulateMonthList();
                    PopulateYearList();
                    InitializeNewReportInstance();

                    progressBar.Visibility = Visibility.Collapsed;
                    lblProgress.Visibility = Visibility.Collapsed;
                    cboRegion.IsEnabled = true;
                    cboDistrict.IsEnabled = true;
                    cboFacility.IsEnabled = true;
                    cboReportYear.IsEnabled = true;
                    cboReportMonth.IsEnabled = true;
                    btnGetReport.IsEnabled = true;
                    btnSave.IsEnabled = true;
                    btnReset.IsEnabled = true;
                }
            }
        }

        public void Reload(FullMTUHAReport newReport, bool disableLocation, bool disableReportTime)
        {
            if (newReport.Above20Form == null)
            {
                newReport.Above20Form = new ANCForm();
                newReport.Above20Form.LessThan20 = false;
            }

            if (newReport.Under20Form == null)
            {
                newReport.Under20Form = new ANCForm();
                newReport.Under20Form.LessThan20 = true;
            }

            PrepareReportBeforeLink(newReport.Under20Form);
            PrepareReportBeforeLink(newReport.Above20Form);

            mtuhaReport = newReport;
            //this.DataContext = null;
            this.DataContext = newReport;

            if (disableLocation)
            {
                cboRegion.IsEnabled = false;
                cboDistrict.IsEnabled = false;
                cboFacility.IsEnabled = false;
            }

            if (disableReportTime)
            {
                cboReportMonth.IsEnabled = false;
                cboReportYear.IsEnabled = false;
            }
        }

        private void PrepareReportBeforeLink(ANCForm report)
        {
            if (report.ANCForm_HudhurioLaKwanza == null) report.ANCForm_HudhurioLaKwanza = new ANCForm_HudhurioLaKwanza();
            if (report.ANCForm_VidokezoVyaHatari == null) report.ANCForm_VidokezoVyaHatari = new ANCForm_VidokezoVyaHatari();
            if (report.ANCForm_PMTCT == null) report.ANCForm_PMTCT = new ANCForm_PMTCT();
            if (report.ANCForm_Malaria == null) report.ANCForm_Malaria = new ANCForm_Malaria();
        }

        public void EnableLocationEdition(bool enabled)
        {
            cboRegion.IsEnabled = enabled;
            cboDistrict.IsEnabled = enabled;
            cboFacility.IsEnabled = enabled;
        }

        public void EnableReportTimeEditing(bool enabled)
        {
            cboReportMonth.IsEnabled = enabled;
            cboReportYear.IsEnabled = enabled;
        }

        private static List<Region> regions = null;
        bool savingReport = false;
        bool gettingReport = false;
        bool loadingRegions = false;
        bool autoUploadToDHIS = true;
        //private OfflineReport offlineReportData = new OfflineReport();

        public ANCMTUHAReport()
        {
            InitializeComponent();
            progressBar.Visibility = Visibility.Collapsed;
            lblProgress.Visibility = Visibility.Collapsed;

            backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += backgroundWorker_DoWork;
            backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
        }

        public ANCMTUHAReport(UserInformation user)
        {
            InitializeComponent();
            progressBar.Visibility = Visibility.Collapsed;
            lblProgress.Visibility = Visibility.Collapsed;

            backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += backgroundWorker_DoWork;
            backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;

            if (regions == null) regions = Utilities.GetDetailedAllRegions(user.SupportingPartnerId, user.UserSignature);
            cboRegion.ItemsSource = regions;
            this.user = user;

            //LoadListOfRegions();
            PopulateMonthList();
            PopulateYearList();
            InitializeNewReportInstance();            
        }

        void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var args = new InteroperableUserControlEventArgs
            {
                StatusText = "Ready",
                Type = InteroperableUserControlEventArgs.StatusType.Text
            };
            if (StatusChanged != null) StatusChanged(this, args);

            #region Saving Operation
            if (savingReport)
            {
                savingReport = false;
                if (e.Error != null)
                {
                    MessageBox.Show(e.Error.Message, AppConfiguration.ApplicationName,
                        MessageBoxButton.OK, MessageBoxImage.Error);
                    btnSave.Content = "Save Changes";
                    btnSave.IsEnabled = true;

                    args = new InteroperableUserControlEventArgs
                    {
                        StatusText = e.Error.Message,
                        Type = InteroperableUserControlEventArgs.StatusType.Text
                    };
                    if (StatusChanged != null) StatusChanged(this, args);
                    return;
                }

                var status = e.Result as ReportingError;
                if (status != null)
                {
                    MessageBoxImage icon = MessageBoxImage.Information;
                    if (status.Type != DataModels.Common.ReportProcessingError.NO_ERROR)
                    {
                        icon = MessageBoxImage.Error;
                    }
                    MessageBox.Show(status.ErrorText, AppConfiguration.ApplicationName,
                            MessageBoxButton.OK, icon);
                }
                else
                {
                    MessageBox.Show("Invalid operation status. It may be caused by old version. " +
                        "\nTry to update then repeat this operation.");
                }

                btnSave.Content = "Save Changes";
                btnSave.IsEnabled = true;
            }
            #endregion

            #region Getting Report
            if (gettingReport)
            {
                gettingReport = false;
                if (e.Error != null)
                {
                    MessageBox.Show(e.Error.Message, AppConfiguration.ApplicationName,
                        MessageBoxButton.OK, MessageBoxImage.Error);
                    btnGetReport.Content = "Get Report";
                    btnGetReport.IsEnabled = true;
                    btnReset.Content = "Reset or Retrieve Existing Report";
                    btnReset.IsEnabled = true; 
                    args = new InteroperableUserControlEventArgs
                    {
                        StatusText = e.Error.Message,
                        Type = InteroperableUserControlEventArgs.StatusType.Text
                    };
                    if (StatusChanged != null) StatusChanged(this, args);
                    return;
                }

                var mtuhaReport = e.Result as FullMTUHAReport;
                if (mtuhaReport != null)
                {
                    this.Reload(mtuhaReport, false, false);
                }
                else
                {
                    MessageBox.Show("Invalid operation status. It may be caused by old version. " +
                            "\nTry to update then repeat this operation.");
                }
                btnGetReport.Content = "Get Report";
                btnGetReport.IsEnabled = true;
                btnReset.Content = "Reset or Retrieve Existing Report";
                btnReset.IsEnabled = true;
            }
            #endregion

            #region Loading Regions
            if (loadingRegions)
            {
                loadingRegions = false;
                if (e.Error != null)
                {
                    progressBar.Visibility = Visibility.Collapsed;
                    lblProgress.HorizontalContentAlignment = HorizontalAlignment.Left;
                    lblProgress.Content = e.Error.Message;
                    lblProgress.FontWeight = FontWeights.Normal;
                    lblProgress.Foreground = Brushes.Red;

                    btnRetryLoadingRegions.Visibility = Visibility.Visible;
                    args = new InteroperableUserControlEventArgs
                    {
                        StatusText = e.Error.Message,
                        Type = InteroperableUserControlEventArgs.StatusType.Text
                    };
                    if (StatusChanged != null) StatusChanged(this, args);
                    return;
                }

                regions = e.Result as List<Region>;
                if (regions != null)
                {
                    cboRegion.ItemsSource = regions;
                    PopulateMonthList();
                    PopulateYearList();
                    InitializeNewReportInstance();

                    progressBar.Visibility = Visibility.Collapsed;
                    lblProgress.Visibility = Visibility.Collapsed;
                    cboRegion.IsEnabled = true;
                    cboDistrict.IsEnabled = true;
                    cboFacility.IsEnabled = true;
                    cboReportYear.IsEnabled = true;
                    cboReportMonth.IsEnabled = true;
                    btnGetReport.IsEnabled = true;
                    btnSave.IsEnabled = true;
                    btnReset.IsEnabled = true;
                }
            }
            #endregion
        }

        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (savingReport)
            {
                //using (var db = new IQSMS_TestDBContext())
                //{
                //    var results = from r in db.MTUHA_Reports
                //                  where r.Name == MTUHA_Reports.ANC_MTUHA_REPORT_VERSION_10_NAME
                //                  select r;
                //    if (results.Count() == 1)
                //    {
                //        var report = results.ToList()[0];
                //        offlineReportData.ReportId = report.Id;
                //        offlineReportData.ReportName = report.Name;
                //    }
                //}

                var reportingText = CreateReportingText();
                if (!string.IsNullOrWhiteSpace(reportingText))
                {
                    //offlineReportData.ReportMessage = reportingText;

                    string username = this.user.Username;
                    string password = DataTransformation.Encrypt(this.user.Password);

                    string authorizationText = null;
                    if (autoUploadToDHIS) authorizationText = DHISDataBridge.DefaultAuthorizationAgent.AuthorizationText;
                    var status = Utilities.SaveMTUHAReport(reportingText, username, password, 
                        mtuhaReport.Above20Form.Comments, autoUploadToDHIS, authorizationText);                    
                    e.Result = status;
                }                
            }

            if (gettingReport)
            {
                string facilityCode = this.mtuhaReport.FacilityCode;
                int year = this.mtuhaReport.ReportYear;
                int month = this.mtuhaReport.ReportMonth;
                int districtId = this.mtuhaReport.DistrictId;
                int regionId = this.mtuhaReport.RegionId;

                var under20Report = Utilities.GetMTUHAReport(facilityCode, year, month, true);
                var above20Report = Utilities.GetMTUHAReport(facilityCode, year, month, false);

                var mtuhaReport = new FullMTUHAReport
                {
                    FacilityCode = facilityCode,
                    DistrictId = districtId,
                    RegionId = regionId,

                    ReportMonth = month,
                    ReportYear = year,

                    Under20Form = under20Report,
                    Above20Form = above20Report
                };

                e.Result = mtuhaReport;
            }

            if (loadingRegions)
            {
                if (regions == null)
                {
                    var results = Utilities.GetDetailedAllRegions(this.user.SupportingPartnerId, this.user.UserSignature);
                    e.Result = results;
                }
                else e.Result = regions;
            }
        }

        private void LoadListOfRegions()
        {
            DataTable dataTable = null;
            Cursor = Cursors.Wait;

            switch (this.user.Level)
            {
                case DataModels.Enumerations.AccessLevel.FACILITY:
                    string facilityCode = this.user.AccessLevelValue;
                    dataTable = Utilities.GetFacilityRegion(facilityCode);
                    //dataTable = Utilities.GetFacilityDetails(facilityCode);
                    break;

                case DataModels.Enumerations.AccessLevel.DISTRICT:
                    int districtID = Int32.Parse(this.user.AccessLevelValue);
                    dataTable = Utilities.GetDistrictRegion(districtID);
                    //dataTable = Utilities.GetFacilitiesDetailsByDistrict(districtID);
                    break;

                case DataModels.Enumerations.AccessLevel.REGION:
                    int regionID = Int32.Parse(this.user.AccessLevelValue);
                    dataTable = Utilities.GetRegion(regionID);
                    //dataTable = Utilities.GetFacilitiesDetailsByRegion(regionID);
                    break;

                case DataModels.Enumerations.AccessLevel.NATION:
                    dataTable = Utilities.GetAllRegions(this.user.SupportingPartnerId);
                    break;

                case DataModels.Enumerations.AccessLevel.ADMINISTRATOR:
                    //dataTable = Utilities.GetAllFacilities();
                    dataTable = Utilities.GetAllRegions();
                    break;
            }
            Cursor = Cursors.Arrow;

            cboRegion.SelectedValuePath = "RegionID";
            cboRegion.DisplayMemberPath = "RegionName";
            cboRegion.ItemsSource = dataTable.DefaultView;
            if (cboRegion.Items.Count > 0) cboRegion.SelectedIndex = 0;
        }

        private void PopulateMonthList()
        {
            DataTable dataTable = new DataTable();
            DataColumn column = new DataColumn("Period", Type.GetType("System.Int32"));
            dataTable.Columns.Add(column);
            column = new DataColumn("Month", Type.GetType("System.String"));
            dataTable.Columns.Add(column);

            DataRow row = null;
            for (int i = 1; i < 13; i++)
            {
                row = dataTable.NewRow();
                row["Period"] = i;
                row["Month"] = Utilities.GetMonthText(i);
                dataTable.Rows.Add(row);
            }

            cboReportMonth.SelectedValuePath = "Period";
            cboReportMonth.DisplayMemberPath = "Month";
            cboReportMonth.ItemsSource = dataTable.DefaultView;
        }

        private void PopulateYearList()
        {
            DataTable dataTable = new DataTable();
            DataColumn column = new DataColumn("Year", Type.GetType("System.Int32"));
            dataTable.Columns.Add(column);

            int currentYear = DateTime.Now.Year;
            DataRow row = dataTable.NewRow();
            row["Year"] = currentYear;
            dataTable.Rows.Add(row);

            row = dataTable.NewRow();
            row["Year"] = currentYear - 1;
            dataTable.Rows.Add(row);

            cboReportYear.DisplayMemberPath = "Year";
            cboReportYear.SelectedValuePath = "Year";
            cboReportYear.ItemsSource = dataTable.DefaultView;
        }

        private void InitializeNewReportInstance()
        {
            this.DataContext = null;
            var lastMonth = DateTime.Now.AddMonths(-1);
            this.mtuhaReport = new FullMTUHAReport
            {
                ReportMonth = lastMonth.Month,
                ReportYear = lastMonth.Year,
                
                Under20Form = new ANCForm
                {
                    C_1 = 0,
                    C_3 = 0,
                    C_7 = 0,
                    C_8 = 0,
                    C_9 = 0,
                    C_10 = 0,
                    ANCForm_HudhurioLaKwanza = new ANCForm_HudhurioLaKwanza(),
                    ANCForm_VidokezoVyaHatari = new ANCForm_VidokezoVyaHatari(),
                    ANCForm_Malaria = new ANCForm_Malaria(),
                    ANCForm_PMTCT = new ANCForm_PMTCT
                    {
                        C_5e = 0,
                        C_5n = 0,
                        C_5o = 0,
                        C_5p = 0
                    }
                },

                Above20Form = new ANCForm
                {
                    C_1 = 0,
                    C_3 = 0,
                    C_7 = 0,
                    C_8 = 0,
                    C_9 = 0,
                    C_10 = 0,
                    ANCForm_HudhurioLaKwanza = new ANCForm_HudhurioLaKwanza(),
                    ANCForm_VidokezoVyaHatari = new ANCForm_VidokezoVyaHatari(),
                    ANCForm_Malaria = new ANCForm_Malaria(),
                    ANCForm_PMTCT = new ANCForm_PMTCT
                    {
                        C_5e = 0,
                        C_5n = 0,
                        C_5o = 0,
                        C_5p = 0
                    }
                }
            };
            this.DataContext = mtuhaReport;
        }

        private void LoadEmptyForm()
        {
            if (cboFacility.SelectedItem != null)
            {
                this.mtuhaReport = new FullMTUHAReport
                {
                    ReportMonth = int.Parse(cboReportMonth.SelectedValue.ToString()),
                    ReportYear = int.Parse(cboReportYear.SelectedValue.ToString()),
                    RegionId = int.Parse(cboRegion.SelectedValue.ToString()),
                    DistrictId = int.Parse(cboDistrict.SelectedValue.ToString()),
                    FacilityCode = cboFacility.SelectedValue.ToString(),

                    Under20Form = new ANCForm
                    {
                        C_1 = 0,
                        C_3 = 0,
                        C_7 = 0,
                        C_8 = 0,
                        C_9 = 0,
                        C_10 = 0,
                        ANCForm_HudhurioLaKwanza = new ANCForm_HudhurioLaKwanza(),
                        ANCForm_VidokezoVyaHatari = new ANCForm_VidokezoVyaHatari(),
                        ANCForm_Malaria = new ANCForm_Malaria(),
                        ANCForm_PMTCT = new ANCForm_PMTCT()
                    },

                    Above20Form = new ANCForm
                    {
                        C_1 = 0,
                        C_3 = 0,
                        C_7 = 0,
                        C_8 = 0,
                        C_9 = 0,
                        C_10 = 0,
                        ANCForm_HudhurioLaKwanza = new ANCForm_HudhurioLaKwanza(),
                        ANCForm_VidokezoVyaHatari = new ANCForm_VidokezoVyaHatari(),
                        ANCForm_Malaria = new ANCForm_Malaria(),
                        ANCForm_PMTCT = new ANCForm_PMTCT()
                    }
                };
                this.DataContext = mtuhaReport;
            }
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textBox = (TextBox)e.OriginalSource;
            // Find the grid row where this item belongs
            int targetRow = Grid.GetRow(textBox);
            const int UNDER_20_COLUMN_INDEX = 2;
            const int ABOVE_20_COLUMN_INDEX = 3;
            const int TOTAL_COLUMN_INDEX = 4;

            TextBox under20 = null, above20 = null;
            Label total = null;
            int count = 0;
            foreach (UIElement element in grid.Children)
            {
                int rowIndex = Grid.GetRow(element);
                if (rowIndex == targetRow)
                {
                    int columnIndex = Grid.GetColumn(element);
                    if (columnIndex == UNDER_20_COLUMN_INDEX)
                    {
                        under20 = element as TextBox;
                        count++;
                    }
                    if (columnIndex == ABOVE_20_COLUMN_INDEX)
                    {
                        above20 = element as TextBox;
                        count++;
                    }
                    if (columnIndex == TOTAL_COLUMN_INDEX)
                    {
                        total = element as Label;
                        count++;
                    }
                }
                if (count == 3) break;
            }

            if (under20 != null && above20 != null && total != null)
            {
                int iUnder20;
                int iAbove20;
                int iTotal;
                bool okToContinue = int.TryParse(under20.Text, out iUnder20);
                if (!okToContinue) iUnder20 = 0;

                okToContinue = okToContinue = int.TryParse(above20.Text, out iAbove20);
                if (!okToContinue) iAbove20 = 0;

                iTotal = iUnder20 + iAbove20;
                total.Content = iTotal;
            }            
        }

        private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            TextBox textBox = null;
            int targetColumnIndex;
            int targetRowIndex;
            Direction direction;
            switch (e.Key)
            {
                case Key.Down:
                    direction = Direction.DOWN;
                    textBox = (TextBox)e.OriginalSource;
                    targetColumnIndex = Grid.GetColumn(textBox);
                    targetRowIndex = Grid.GetRow(textBox) + 1;
                    if (grid.RowDefinitions.Count == targetRowIndex) return;
                    else
                    {
                        SetFocusToTheNextTextBox(targetRowIndex, targetColumnIndex, direction);
                        e.Handled = true;
                    }
                    break;

                case Key.Up:
                    direction = Direction.UP;
                    textBox = (TextBox)e.OriginalSource;
                    targetColumnIndex = Grid.GetColumn(textBox);
                    targetRowIndex = Grid.GetRow(textBox) - 1;
                    if (targetRowIndex == -1) return;
                    else
                    {
                        SetFocusToTheNextTextBox(targetRowIndex, targetColumnIndex, direction);
                        e.Handled = true;
                    }
                    break;

                case Key.Left:
                    direction = Direction.LEFT;
                    textBox = (TextBox)e.OriginalSource;
                    targetColumnIndex = Grid.GetColumn(textBox) - 1;
                    targetRowIndex = Grid.GetRow(textBox);
                    if (targetColumnIndex == -1) return;
                    else
                    {
                        SetFocusToTheNextTextBox(targetRowIndex, targetColumnIndex, direction);
                        e.Handled = true;
                    }
                    break;

                case Key.Right:
                    direction = Direction.RIGHT;
                    textBox = (TextBox)e.OriginalSource;
                    targetColumnIndex = Grid.GetColumn(textBox) + 1;
                    targetRowIndex = Grid.GetRow(textBox);
                    if (grid.ColumnDefinitions.Count == targetColumnIndex) return;
                    else
                    {
                        SetFocusToTheNextTextBox(targetRowIndex, targetColumnIndex, direction);
                        e.Handled = true;
                    }
                    break;
            }
        }

        private void SetFocusToTheNextTextBox(int targetRowIndex, int targetColumnIndex, Direction direction)
        {
            bool repeatSearch = default(bool);
            do
            {
                repeatSearch = SearchNextTextBox(targetRowIndex, targetColumnIndex);
                if (direction == Direction.DOWN) targetRowIndex++;
                if (direction == Direction.UP) targetRowIndex--;
                if (direction == Direction.LEFT) targetColumnIndex--;
                if (direction == Direction.RIGHT) targetColumnIndex++;
            } while (repeatSearch);            
        }

        private bool SearchNextTextBox(int targetRowIndex, int targetColumnIndex)
        {
            const int LABEL_ROW_SPAN = 4;
            bool repeatSearch = false;
            foreach (UIElement element in grid.Children)
            {
                int rowIndex = Grid.GetRow(element);
                if (rowIndex == targetRowIndex)
                {
                    int columnIndex = Grid.GetColumn(element);
                    if (columnIndex == targetColumnIndex)
                    {
                        var textBox = element as TextBox;
                        if (textBox != null)
                        {
                            if (textBox.IsReadOnly) repeatSearch = true;
                            else
                            {
                                textBox.Focus();
                                textBox.SelectAll();
                                return false;
                            }
                        }
                    }
                    else
                    {
                        var label = element as Label;
                        if (label != null)
                        {
                            int columnSpan = Grid.GetColumnSpan(label);
                            if (columnSpan == LABEL_ROW_SPAN)
                            {
                                // Re-construct the target row to be the next
                                repeatSearch = true;
                            }
                        }
                    }
                }
            }
            return repeatSearch;
        }

        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (this.mtuhaReport != null)
                {
                    Facility facility = cboFacility.SelectedItem as Facility;
                    if (cboFacility.SelectedItem != null && cboReportMonth.SelectedItem != null
                        && cboReportYear.SelectedItem != null)
                    {
                        foreach (UIElement element in grid.Children)
                        {
                            TextBox textBox = element as TextBox;
                            if (textBox != null)
                            {
                                if (textBox.Visibility == System.Windows.Visibility.Visible &&
                                    string.IsNullOrWhiteSpace(textBox.Text))
                                {
                                    textBox.Focus();
                                    MessageBox.Show("Please fill all the required fields", "Incomplete Form",
                                        MessageBoxButton.OK, MessageBoxImage.Warning);
                                    return;
                                }
                            }
                        }

                        // Preparing offline data
                        //offlineReportData.FacilityCode = facility.Code;
                        //offlineReportData.FacilityName = facility.Name;
                        //offlineReportData.CreatedByUserId = this.User.ID;
                        //offlineReportData.CreatedByUserName = this.User.FullName;
                        //offlineReportData.ReportMonth = this.mtuhaReport.ReportMonth;
                        //offlineReportData.ReportYear = this.mtuhaReport.ReportYear;
                        //offlineReportData.Indicators = new List<OfflineReportIndicator>();
                        //offlineReportData.DateSavedOffline = DateTime.Now;
                        
                        autoUploadToDHIS = true;   // Default is auto-upload
                        if (chbAutoUpload.IsChecked.HasValue)
                        {
                            if (chbAutoUpload.IsChecked.Value)
                            {
                                if (DHISDataBridge.DefaultAuthorizationAgent == null)
                                {
                                    DHISDataBridge.DefaultBaseUrl = AppConfiguration.DHISBaseUrl;
                                    var dhisLogin = new DHISLogin();
                                    dhisLogin.ShowInTaskbar = true;
                                    bool? result = dhisLogin.ShowDialog();

                                    if (result.HasValue && result.Value) DHISDataBridge.DefaultAuthorizationAgent = dhisLogin.Agent;
                                    else return;
                                }
                            }
                            else autoUploadToDHIS = false;
                        }

                        savingReport = true;
                        backgroundWorker.RunWorkerAsync(); 
                        var args = new InteroperableUserControlEventArgs
                        {
                            StatusText = "Please wait...",
                            Type = InteroperableUserControlEventArgs.StatusType.Text
                        };
                        if (StatusChanged != null) StatusChanged(this, args);
                        btnSave.Content = "Please wait...";
                        btnSave.IsEnabled = false;
                    }                    
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, AppConfiguration.ApplicationName,
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        #region Creation of Reporting Text
        private string CreateReportingText()
        {
            string reportKeywords = GenericTools.Utilities.GetSetting(ANCFormValidator.SETTINGS_KEY_ANC_MTUHA_REPORT_KEYWORDS);
            if (string.IsNullOrEmpty(reportKeywords))
            {
                GenericTools.Utilities.SetSetting(ANCFormValidator.SETTINGS_KEY_ANC_MTUHA_REPORT_KEYWORDS, ANCFormValidator.DEFAULT_ANC_MTUHA_REPORT_KEYWORDS);
                reportKeywords = ANCFormValidator.DEFAULT_ANC_MTUHA_REPORT_KEYWORDS;
            }

            string keyword = reportKeywords.Split('|')[0];
            string facilityCode = this.mtuhaReport.FacilityCode;
            int year = this.mtuhaReport.ReportYear;
            int month = this.mtuhaReport.ReportMonth;

            string segmentPrefix = Utilities.GetSetting(ANCFormValidator.SETTINGS_KEY_MTUHA_REPORT_SECTION_KEYWORD);
            string under20Keyword = Utilities.GetSetting(ANCFormValidator.SETTINGS_KEY_MTUHA_REPORT_UNDER_20_KEYWORD);
            string above20Keyword = Utilities.GetSetting(ANCFormValidator.SETTINGS_KEY_MTUHA_REPORT_ABOVE_20_KEYWORD);

            string mainFormUnder20 = GetSegmentForMainReport(under20Keyword, segmentPrefix, mtuhaReport.Under20Form);
            string mainFormAbove20 = GetSegmentForMainReport(above20Keyword, segmentPrefix, mtuhaReport.Above20Form);

            string hudhurioUnder20 = Method2(under20Keyword, segmentPrefix,
                mtuhaReport.Under20Form.ANCForm_HudhurioLaKwanza);
            string hudhurioAbove20 = Method2(above20Keyword, segmentPrefix,
                mtuhaReport.Above20Form.ANCForm_HudhurioLaKwanza);

            string vidokezoUnder20 = Method2(under20Keyword, segmentPrefix,
                mtuhaReport.Under20Form.ANCForm_VidokezoVyaHatari);
            string vidokezoAbove20 = Method2(above20Keyword, segmentPrefix,
                mtuhaReport.Above20Form.ANCForm_VidokezoVyaHatari);

            string pmtctUnder20 = Method2(under20Keyword, segmentPrefix, mtuhaReport.Under20Form.ANCForm_PMTCT);
            string pmtctAbove20 = Method2(above20Keyword, segmentPrefix, mtuhaReport.Above20Form.ANCForm_PMTCT);

            string malariaUnder20 = Method2(under20Keyword, segmentPrefix,
                mtuhaReport.Under20Form.ANCForm_Malaria);
            string malariaAbove20 = Method2(above20Keyword, segmentPrefix,
                mtuhaReport.Above20Form.ANCForm_Malaria);

            string reportingText = string.Format("{0}.{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}",
                keyword, facilityCode, month, year, mainFormUnder20, mainFormAbove20,
                hudhurioUnder20, hudhurioAbove20, vidokezoUnder20, vidokezoAbove20,
                pmtctUnder20, pmtctAbove20, malariaUnder20, malariaAbove20);

            return reportingText;
        }

        private static string Method2(string ageCategoryKeyword, string segmentPrefix,
            MTUHAReportBase formSectionData)
        {
            bool sectionNumberFound = false;
            var sBuilder = new StringBuilder();

            var properties = formSectionData.GetType().GetProperties();
            foreach (var property in properties)
            {
                if (property.Name.StartsWith("C_", StringComparison.OrdinalIgnoreCase))
                {
                    if (!sectionNumberFound)
                    {
                        string sectionNumber = Regex.Match(property.Name, @"\d+").Value;
                        sBuilder.Append(ageCategoryKeyword + "," + segmentPrefix + sectionNumber);
                        sectionNumberFound = true;
                    }
                    object v = property.GetValue(formSectionData, null);
                    try
                    {
                        int value = int.Parse(v.ToString());
                        sBuilder.Append("," + value);
                    }
                    catch
                    {
                        throw new Exception("Invalid value at " + property.Name);
                    }
                }
            }

            return sBuilder.ToString();
        }

        private static string GetSegmentForMainReport(string ageCategoryKeyword, string segmentPrefix, ANCForm form)
        {
            //C20,K1,1,K3,2,K7,3,K8,4,K9,5,K10,6
            return string.Format("{0},{1}1,{2},{0},{1}3,{3},{0},{1}7,{4},{0},{1}8,{5},{0},{1}9,{6},{0},{1}10,{7}", 
                ageCategoryKeyword, segmentPrefix,
                form.C_1, form.C_3, form.C_7, form.C_8, form.C_9, form.C_10);
        }

        #region Obsolete Methods - No longer relevant
        [Obsolete("Find another way of implementing this without using this method", true)]
        private static string GetHudhurioLaKwanzaSegment(string ageCategoryKeyword, string segmentPrefix, 
            ANCForm_HudhurioLaKwanza form)
        {
            return string.Format("{0},{1}2,{2},{3},{4},{5},{6},{7},{8}",
                ageCategoryKeyword, segmentPrefix,
                form.C_2a, form.C_2b, form.C_2c, form.C_2d, form.C_2e, form.C_2f, form.C_2g);
        }

        [Obsolete("Find another way of implementing this without using this method", true)]
        private static string GetVidokezoVyaHatariSegment(string ageCategoryKeyword, string segmentPrefix,
            ANCForm_VidokezoVyaHatari form)
        {
            return string.Format("{0},{1}4,{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}",
                ageCategoryKeyword, segmentPrefix,
                form.C_4a, form.C_4b, form.C_4c, form.C_4d, form.C_4e, form.C_4f, form.C_4g, 
                form.C_4h, form.C_4i, form.C_4j, form.C_4k);
        }

        [Obsolete("Find another way of implementing this without using this method", true)]
        private static string GetPMTCTSegment(string ageCategoryKeyword, string segmentPrefix,
            ANCForm_PMTCT form)
        {
            return string.Format("{0},{1}5,{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14}",
                ageCategoryKeyword, segmentPrefix,
                form.C_5a, form.C_5b, form.C_5c, form.C_5d, form.C_5e, form.C_5f, form.C_5g,
                form.C_5h, form.C_5i, form.C_5j, form.C_5k, form.C_5l, form.C_5m);
        }

        [Obsolete("Find another way of implementing this without using this method", true)]
        private static string GetMalariaSegment(string ageCategoryKeyword, string segmentPrefix,
            ANCForm_Malaria form)
        {
            return string.Format("{0},{1}6,{2},{3},{4},{5},{6}",
                ageCategoryKeyword, segmentPrefix,
                form.C_6a, form.C_6b, form.C_6c, form.C_6d, form.C_6e);
        }
        #endregion
        #endregion

        private void Method(Button targetButton)
        {
            var facility = cboFacility.SelectedItem as DataModels.Models.Facility;
            if (facility == null)
            {
                MessageBox.Show("Please select facility", AppConfiguration.ApplicationName,
                    MessageBoxButton.OK, MessageBoxImage.Stop);
                cboFacility.Focus();
                return;
            }

            var month = cboReportMonth.SelectedValue as int?;
            if (!month.HasValue)
            {
                MessageBox.Show("Please select month", AppConfiguration.ApplicationName,
                    MessageBoxButton.OK, MessageBoxImage.Stop);
                cboReportMonth.Focus();
                return;
            }

            var year = cboReportYear.SelectedValue as int?;
            if (!year.HasValue)
            {
                MessageBox.Show("Please select month", AppConfiguration.ApplicationName,
                    MessageBoxButton.OK, MessageBoxImage.Stop);
                cboReportMonth.Focus();
                return;
            }

            try
            {
                gettingReport = true;
                backgroundWorker.RunWorkerAsync();
                targetButton.Content = "Please wait..."; 
                var args = new InteroperableUserControlEventArgs
                {
                    StatusText = "Please wait...",
                    Type = InteroperableUserControlEventArgs.StatusType.Text
                };
                if (StatusChanged != null) StatusChanged(this, args);
                targetButton.IsEnabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, AppConfiguration.ApplicationName,
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void btnGetReport_Click(object sender, RoutedEventArgs e)
        {
            Method(btnGetReport);
        }

        private void btnReset_Click(object sender, RoutedEventArgs e)
        {
            Method(btnReset);
        }

        private void btnRetryLoadingRegions_Click(object sender, RoutedEventArgs e)
        {
            btnRetryLoadingRegions.Visibility = Visibility.Collapsed;
            
            lblProgress.HorizontalContentAlignment = HorizontalAlignment.Center;
            lblProgress.Content = "Loading Data. Please wait...";
            lblProgress.FontWeight = FontWeights.Bold;
            lblProgress.Foreground = Brushes.Black;

            progressBar.Visibility = Visibility.Visible;
            loadingRegions = true;
            backgroundWorker.RunWorkerAsync();
            var args = new InteroperableUserControlEventArgs
            {
                StatusText = "Loading Data. Please wait...",
                Type = InteroperableUserControlEventArgs.StatusType.Text
            };
            if (StatusChanged != null) StatusChanged(this, args);
        }

        #region For operations when included in the parent control
        public void SaveChanges()
        {
            btnSave_Click(null, null);
        }

        public void Reset()
        {
            btnReset_Click(null, null);
        }
        #endregion

        private void cboFacility_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (gridActionPanel.Visibility == System.Windows.Visibility.Visible) LoadEmptyForm();
        }

        private void cboReportMonth_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (gridActionPanel.Visibility == System.Windows.Visibility.Visible) LoadEmptyForm();
        }

        private void btnClearForm_Click(object sender, RoutedEventArgs e)
        {
            if (gridActionPanel.Visibility == System.Windows.Visibility.Visible) LoadEmptyForm();
        }

        private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            var textBox = e.OriginalSource as TextBox;
            if (textBox != null)
            {
                textBox.SelectAll();
                int row = Grid.GetRow(textBox);
                foreach (UIElement element in grid.Children)
                {
                    int r = Grid.GetRow(element);
                    if (r == row)
                    {
                        var control = element as Control;
                        if (control != null) control.Background = Brushes.LightYellow;
                    }
                    if (r > row) break;
                }
            }
        }

        private void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            var textBox = e.OriginalSource as TextBox;
            if (textBox != null)
            {
                int row = Grid.GetRow(textBox);
                foreach (UIElement element in grid.Children)
                {
                    int r = Grid.GetRow(element);
                    if (r == row)
                    {
                        var control = element as Control;
                        if (control != null) control.ClearValue(Control.BackgroundProperty);
                    }
                    if (r > row) break;
                }
            }
        }
    }
}
